/*
 * 版权所有 (C) 2015 知启蒙(ZHIQIM) 保留所有权利。[欢迎加盟知启蒙，一起邂逅框架梦]
 * 
 * https://www.zhiqim.com/gitcan/zhiqim/zhiqim_account.htm
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.zhiqim.account.action.pay;

import org.zhiqim.account.api.pay.AlipayServer;
import org.zhiqim.account.dbo.user.UserTradeAlipay;
import org.zhiqim.account.paycallback.PayCallback;
import org.zhiqim.httpd.HttpRequest;
import org.zhiqim.httpd.context.core.Action;
import org.zhiqim.kernel.Global;
import org.zhiqim.kernel.logging.Log;
import org.zhiqim.kernel.logging.LogFactory;
import org.zhiqim.kernel.util.Sqls;
import org.zhiqim.kernel.util.Validates;
import org.zhiqim.orm.ZTable;
import org.zhiqim.orm.dbo.Updater;

import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayConstants;
import com.alipay.api.internal.util.AlipaySignature;
import com.alipay.api.response.AlipayTradeQueryResponse;

/**
 * 电脑网站支付结果异步通知
 * https://docs.open.alipay.com/270/105902/
 * 
 *
 *  公共参数
 * notify_time  通知时间
 * notify_type  通知类型
 * notify_id    通知校验ID
 * charset  编码格式
 * version  接口版本
 * sign_type    签名类型
 * sign     签名
 * auth_app_id  授权方的app_id
 * 
 *  业务参数
 *  trade_no    支付宝交易号
 *  app_id  开发者的app_id
 *  out_trade_no    商户订单号
 *  out_biz_no  商户业务号
 *  buyer_id    买家支付宝用户号
 *  seller_id   卖家支付宝用户号
 *  trade_status    交易状态
 *  total_amount    订单金额
 *  ...
 * 
 * @version v1.0.0 @author yangpeng 2018-2-27 新建与整理
 * @version v1.0.1 @author zouzhigang 208-3-26 修改交易编号为trade_id为long型
 */
public class AlipayNotifyAction implements Action, AlipayConstants
{
    private static final Log log = LogFactory.getLog(AlipayNotifyAction.class);
    
    public void execute(HttpRequest request) throws Exception
    {
        //第一步，从内容中取出参数
        long tradeId = request.getParameterLongOnCNT("out_trade_no");
        String tradeNo = request.getParameterOnCNT("trade_no");
        String notifyTime = request.getParameterOnCNT("notify_time");
        String tradeStatus = request.getParameterOnCNT("trade_status");
        String notifyId = request.getParameterOnCNT("notify_id");
        
        try
        {//第二步，验证参数正确性
            String alipayPublicKey = Global.getService(AlipayServer.class).getAlipayPublicKey();
            boolean signVerified = AlipaySignature.rsaCheckV1(request.getParameterMapOnCNT(), alipayPublicKey, CHARSET_UTF8, SIGN_TYPE_RSA2);
            if(!signVerified)
            {
                log.error("收到支付宝交易通知["+notifyId+"]["+tradeNo+"]["+tradeStatus+"]数据验证失败");
                return;
            }
        }
        catch(AlipayApiException e)
        {
            log.error("收到支付宝交易通知["+notifyId+"]["+tradeNo+"]["+tradeStatus+"]API验证异常");
            return;
        }
        
        //第三步，从支付宝交易表中取出交易详情
        UserTradeAlipay alipay = Global.get(ZTable.class).item(UserTradeAlipay.class, tradeId);
        if(alipay == null)
        {
            log.info("收到支付宝交易通知["+notifyId+"]["+tradeNo+"]["+tradeStatus+"]交易不存在");
            request.getResponse().print("success");
            return;
        }
        
        //第四步，更新交易数据，共五项，四项基本数据+支付宝账号
        alipay.setTradeNo(tradeNo);
        alipay.setTradeStatus(tradeStatus);
        alipay.setTradeNotified(Sqls.toTimestamp(notifyTime));
        alipay.setTradeNotifyDesc(request.getParameterMapOnCNT().toString());
        
        Updater updater = new Updater();
        updater.addMust("tradeId", tradeId);
        updater.addField("tradeNo", alipay.getTradeNo());
        updater.addField("tradeStatus", alipay.getTradeStatus());
        updater.addField("tradeNotified", alipay.getTradeNotified());
        updater.addField("tradeNotifyDesc", alipay.getTradeNotifyDesc());
        
        if (Validates.isEmpty(alipay.getTradeAccount()))
        {//查询支付宝账号
            AlipayTradeQueryResponse response = Global.getService(AlipayServer.class).tradeQuery(tradeId, tradeNo);
            if(response.isSuccess())
            {//买家支付宝账号
                alipay.setTradeAccount(response.getBuyerLogonId());
                updater.addField("tradeAccount", alipay.getTradeAccount());
            }
        }
        
        Global.get(ZTable.class).update(UserTradeAlipay.class, updater);
        
        //第五步，查询内部订单，已处理的不再处理
        String callback = alipay.getTradeCallback();

        Object obj = Global.getCreate(Global.getClass(callback));
        PayCallback call = (PayCallback)obj;
        call.call(alipay, true);
        
        //第六步，响应支付宝端成功
        request.getResponse().print("success");
    }
}
